"""
Copyright 2012 Wieser Dietmar, Margit Mutschlechner.

This file is part of Multimedia Social Networking Platform.

Multimedia Social Networking Platform is free software: 
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Multimedia Social Networking Platform is distributed
in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Multimedia Social Networking Platform.  
If not, see <http://www.gnu.org/licenses/>.

"""

import xml.parsers.expat
from xml.dom.minidom import Document
import traceback
from msnp.logger import Logger
from msnp.model import SettingsModel

__settings = None
__userSettings = None

##########
## TAGS ##
##########
__TAG_SETTINGS = "settings"
__TAG_GROUP = "group"
__TAG_USER = "user"
__TAG_LAST_LOGIN_USERNAME = "lastLoginUsername"
__TAG_PLAYER_DATABASE = "playerDB"
__TAG_MSNP_DATABASE = "networkDB"
__TAG_MEDIA_DATABASE = "mediaDB"
__TAG_LAST_PLAYER_SYNCH = "lastPlayerSynch"
__TAG_START_PORT = "startPort"
__TAG_END_PORT = "endPort"

################
## ATTRIBUTES ##
################
__ATTR_GROUP_NAME = "name"
__ATTR_GROUP_OWNER = "owner"
__ATTR_GROUP_INSYNCH = "inSynch"
__ATTR_GROUP_OUTSYNCH = "outSynch"
__ATTR_USER_NAME = "name"
__ATTR_PDB_PLAYER = "player"
__ATTR_PDB_HOST = "host"
__ATTR_PDB_USER = "user"
__ATTR_PDB_PASSWORD = "password"
__ATTR_PDB_SCHEMA = "schema"
__ATTR_LAST_PLAYER_SYNCH_ID = "lastProcessedId"
__ATTR_LAST_PLAYER_SYNCH_DATE = "date"
__ATTR_PORT = "port"

def __start_element(name, attrs):
    """This function is called by the parser on every starting tag. Depending on the tag it stores the attributes locally in a Settings object.
    
    Args:
        name: A String containing the name of the tag.
        attrs: A list of Strings containing the attributes of the tag.
    """
    global __settings
    global __userSettings
    try:
        if name == __TAG_GROUP:
            groupname = attrs.get(__ATTR_GROUP_NAME)
            ownername = attrs.get(__ATTR_GROUP_OWNER)
            synchOut = attrs.get(__ATTR_GROUP_OUTSYNCH)
            synchIn = attrs.get(__ATTR_GROUP_INSYNCH)
            newGroup = SettingsModel.GroupSettings(groupname, ownername, synchOut == "True", synchIn == "True")
            __userSettings.addGroupSettings(newGroup)
        elif name == __TAG_USER:
            if __userSettings != None:
                __settings.addUserSettings(__userSettings)
            __userSettings = SettingsModel.UserSettings()
            __userSettings.setUsername(attrs.get(__ATTR_USER_NAME))
        elif name == __TAG_PLAYER_DATABASE:
            player = attrs.get(__ATTR_PDB_PLAYER)
            host = attrs.get(__ATTR_PDB_HOST)
            user = attrs.get(__ATTR_PDB_USER)
            password = attrs.get(__ATTR_PDB_PASSWORD)
            schema = attrs.get(__ATTR_PDB_SCHEMA)
            playerSettings = SettingsModel.DatabaseSettings(host, user, password, schema, player)
            __userSettings.setPlayerDatabaseSettings(playerSettings)
        elif name == __TAG_MSNP_DATABASE:
            host = attrs.get(__ATTR_PDB_HOST)
            user = attrs.get(__ATTR_PDB_USER)
            password = attrs.get(__ATTR_PDB_PASSWORD)
            schema = attrs.get(__ATTR_PDB_SCHEMA)
            msnpSettings = SettingsModel.DatabaseSettings(host, user, password, schema, "")
            __userSettings.setMSNPDatabaseSettings(msnpSettings)
        elif name == __TAG_MEDIA_DATABASE:
            host = attrs.get(__ATTR_PDB_HOST)
            user = attrs.get(__ATTR_PDB_USER)
            password = attrs.get(__ATTR_PDB_PASSWORD)
            schema = attrs.get(__ATTR_PDB_SCHEMA)
            mediaSettings = SettingsModel.DatabaseSettings(host, user, password, schema, "")
            __userSettings.setMediaDatabaseSettings(mediaSettings)
        elif name == __TAG_LAST_PLAYER_SYNCH:
            lastProcessedId = int(attrs.get(__ATTR_LAST_PLAYER_SYNCH_ID))
            date = attrs.get(__ATTR_LAST_PLAYER_SYNCH_DATE)
            lastPlayerSynch = SettingsModel.LastPlayerSynch(lastProcessedId, date)
            __userSettings.setLastPlayerSynch(lastPlayerSynch)
        elif name == __TAG_START_PORT:
            __userSettings.setStartPort(attrs.get(__ATTR_PORT))
        elif name == __TAG_END_PORT:
            __userSettings.setEndPort(attrs.get(__ATTR_PORT))
        elif name == __TAG_LAST_LOGIN_USERNAME:
            __settings.setLastLoginUsername(attrs.get(__ATTR_USER_NAME))
        elif name == __TAG_SETTINGS:
            pass
        else:
            Logger.info("tag unknown in settings accessor __start_element: '" + name + "'")
    except:
        Logger.info("exception in settings accessor __start_element")
        Logger.info(traceback.format_exc())
        
def __writeSettings(filename):
    """This functions writes the locally stored settings into the settings file.
    
    Args:
        filename: A String containing the name of the settings file.
    
    Returns:
        True is returned if the writing was successful, False otherwise.
    """
    global __settings
    try:
        doc = Document()
        # Create the settings base element
        settingsElement = doc.createElement(__TAG_SETTINGS)
        doc.appendChild(settingsElement)
        # Create the last user name element
        lastUsername = doc.createElement(__TAG_LAST_LOGIN_USERNAME)
        lastUsername.setAttribute(__ATTR_USER_NAME, __settings.getLastLoginUsername())
        settingsElement.appendChild(lastUsername)
        # Create the user elements
        if __settings.getUserSettings() != None and len(__settings.getUserSettings()) > 0:
            for userSettings in __settings.getUserSettings():
                user = doc.createElement(__TAG_USER)
                user.setAttribute(__ATTR_USER_NAME, userSettings.getUsername())
                settingsElement.appendChild(user)
                # Create player db element
                playerDB = doc.createElement(__TAG_PLAYER_DATABASE)
                playerDB.setAttribute(__ATTR_PDB_PLAYER, userSettings.getPlayerDatabaseSettings().getPlayer())
                playerDB.setAttribute(__ATTR_PDB_HOST, userSettings.getPlayerDatabaseSettings().getHost())
                playerDB.setAttribute(__ATTR_PDB_USER, userSettings.getPlayerDatabaseSettings().getUser())
                playerDB.setAttribute(__ATTR_PDB_PASSWORD, userSettings.getPlayerDatabaseSettings().getPassword())
                playerDB.setAttribute(__ATTR_PDB_SCHEMA, userSettings.getPlayerDatabaseSettings().getSchema())
                user.appendChild(playerDB)
                # Create msnp db element
                msnpDB = doc.createElement(__TAG_MSNP_DATABASE)
                msnpDB.setAttribute(__ATTR_PDB_HOST, userSettings.getMSNPDatabaseSettings().getHost())
                msnpDB.setAttribute(__ATTR_PDB_USER, userSettings.getMSNPDatabaseSettings().getUser())
                msnpDB.setAttribute(__ATTR_PDB_PASSWORD, userSettings.getMSNPDatabaseSettings().getPassword())
                msnpDB.setAttribute(__ATTR_PDB_SCHEMA, userSettings.getMSNPDatabaseSettings().getSchema())
                user.appendChild(msnpDB)
                # Create media db element
                mediaDB = doc.createElement(__TAG_MEDIA_DATABASE)
                mediaDB.setAttribute(__ATTR_PDB_HOST, userSettings.getMediaDatabaseSettings().getHost())
                mediaDB.setAttribute(__ATTR_PDB_USER, userSettings.getMediaDatabaseSettings().getUser())
                mediaDB.setAttribute(__ATTR_PDB_PASSWORD, userSettings.getMediaDatabaseSettings().getPassword())
                mediaDB.setAttribute(__ATTR_PDB_SCHEMA, userSettings.getMediaDatabaseSettings().getSchema())
                user.appendChild(mediaDB)
                # Create last player synch element
                lastPlayerSynch = doc.createElement(__TAG_LAST_PLAYER_SYNCH)
                lastPlayerSynch.setAttribute(__ATTR_LAST_PLAYER_SYNCH_ID, str(userSettings.getLastPlayerSynch().getLastProcessedId()))
                lastPlayerSynch.setAttribute(__ATTR_LAST_PLAYER_SYNCH_DATE, str(userSettings.getLastPlayerSynch().getDate()))
                user.appendChild(lastPlayerSynch)
                # create start port element
                startPort = doc.createElement(__TAG_START_PORT)
                startPort.setAttribute(__ATTR_PORT, userSettings.getStartPort())
                user.appendChild(startPort)
                # create end port element
                endPort = doc.createElement(__TAG_END_PORT)
                endPort.setAttribute(__ATTR_PORT, userSettings.getEndPort())
                user.appendChild(endPort)
                # Create group elements
                if userSettings.getGroupSettingsList() != None and len(userSettings.getGroupSettingsList()) > 0:
                    for groupSettings in userSettings.getGroupSettingsList():
                        group = doc.createElement(__TAG_GROUP)
                        group.setAttribute(__ATTR_GROUP_NAME, groupSettings.getGroupname())
                        group.setAttribute(__ATTR_GROUP_OWNER, groupSettings.getOwnername())
                        group.setAttribute(__ATTR_GROUP_INSYNCH, str(groupSettings.isSynchIn()))
                        group.setAttribute(__ATTR_GROUP_OUTSYNCH, str(groupSettings.isSynchOut()))
                        user.appendChild(group)
        #print doc.toprettyxml(indent='\t')
        f = open(filename, 'w')
        doc.writexml(f)
        f.close()
        return True
    except:
        Logger.info("exception while storing settings")
        Logger.info(traceback.format_exc())
    return False

def __executeParsing(filename):
    """This functions reads the given settings file and stores them locally as Settings object.
    
    Args:
        filename: A String containing the name of the settings file.
    """
    global __settings
    global __userSettings
    try:
        f = open(filename, 'r')
        s = f.read()
        p = xml.parsers.expat.ParserCreate()
        p.StartElementHandler = __start_element
        p.Parse(s, 1)
    except:
        Logger.info("Exception while parsing settings")
        Logger.info(traceback.format_exc())
        __settings = None
    #we have to add the last user iteration
    if __userSettings != None:
        __settings.addUserSettings(__userSettings)
        __userSettings = None
    if __settings != None and __settings.getLastLoginUsername() == None:
        __settings = None
        
def parseSettings(filename):
    """This functions reads the settings file, or if it was already read once, it returns the locally stored Settings object.
    
    Args:
        filename: A String containing the name of the settings file.
    
    Returns:
        It returns a Settings object containing the read settings information.
    """
    global __settings
    global __userSettings
    if __settings == None:
        __settings = SettingsModel.Settings()
        __executeParsing(filename)
    return __settings

def storeSettings(filename, newSettings):
    """This functions stores the given settings into the settings file and stores them locally.
    
    Args:
        filename: A String containing the name of the settings file.
        newSettings: A Settings object which should be written into the settings file.
    
    Returns:
        True is returned if the writing was successful, False otherwise.
    """
    global __settings
    __settings = newSettings
    return __writeSettings(filename)
